/**
 * Alipay.com Inc.
 * Copyright (c) 2004-2013 All Rights Reserved.
 */
package com.loser.csp.webapp.gateway;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.DirectFieldBindingResult;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.loser.csp.common.gateway.model.BaseRequest;
import com.loser.csp.common.gateway.model.GatewayParasKeys;
import com.loser.csp.common.gateway.model.enums.ResultStatusEnum;
import com.loser.csp.common.gateway.service.ServiceProcessor;
import com.loser.csp.common.gateway.service.ServiceProcessorFactory;
import com.loser.csp.common.gateway.service.result.AppServerResult;
import com.loser.csp.common.gateway.service.result.BaseBizResultObj;
import com.loser.csp.common.gateway.utils.JsonUtil;
import com.loser.csp.common.gateway.utils.StringUtil;

/**
 * 网关请求入口
 * @author shuyan.zsy
 * @version $Id: RpcGateway.java, v 0.1 2013-12-18 上午10:20:45 shuyan.zsy Exp $
 */
@Controller
public class RpcGateway {

    private static final Logger     logger = Logger.getLogger(RpcGateway.class);

    @Autowired
    private ServiceProcessorFactory serviceProcessorFactory;

    
 

	@RequestMapping(value="/test1.html")
    public String test(String name){
    	System.out.println("---------2222----");
    	return "error";
    }

    /**
     * 执行请求
     * 
     * @param request
     * @param modelMap
     * @return
     */
    @RequestMapping(value = "/gateway.html", method = { RequestMethod.GET, RequestMethod.POST })
    public void execute(@RequestParam(value = "requestData", required = false)
    String requestData, HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {
        AppServerResult result = new AppServerResult();
        if (logger.isInfoEnabled()) {
            logger.info("进入RPC GateWay，requestData：" + requestData);
        }
        if (StringUtil.isBlank(requestData)) {
            this.responseErrorInfo(response, result, ResultStatusEnum.REQUEST_DATA_ERROR);
            return;
        }
        requestData = requestData.replaceAll("\\r\\n", "");

        String service = JsonUtil.getParameter(requestData, GatewayParasKeys.SERVICE);
        if (StringUtil.isBlank(service)) {
            this.responseErrorInfo(response, result, ResultStatusEnum.REQUEST_DATA_ERROR);
            return;
        }

        //1.获取业务处理器
        ServiceProcessor serviceProcessor = serviceProcessorFactory.getProcessor(service);
        if (serviceProcessor == null) {
            this.responseErrorInfo(response, result, ResultStatusEnum.SERVICE_NOT_EXIST);
            return;
        }

        //2.请求转换
        BaseRequest bizRequest = null;
        try {
            bizRequest = (BaseRequest) JsonUtil.json2ObjectIgnore(requestData, serviceProcessor
                .getRequestClass());
        } catch (Exception e) {
            logger.error("转换成bizRequest失败,requestData=" + requestData, e);
            this.responseErrorInfo(response, result, ResultStatusEnum.REQUEST_DATA_ERROR);
            return;
        }

        // 2.校验请求参数
        /** 校验器 */
        Errors errors = new DirectFieldBindingResult(bizRequest, "bizRequest");
       // validator.validate(bizRequest, errors);
        if (errors.hasErrors()) {
            logger.error("校验参数失败。参数" + errors.getFieldError().getField() + "，校验失败，错误原因："
                         + errors.getFieldError().getCode() + "，参数值："
                         + errors.getFieldError().getRejectedValue());
            this.responseErrorInfo(response, result, ResultStatusEnum.REQUEST_DATA_ERROR);
            return;
        }

        //4.安全性校验
        boolean safeValidResult = this.validateSafe(request, response, result, bizRequest);
        if (!safeValidResult) {
            this.responsData(response, result);
            return;
        }

        //5. 执行请求
        BaseBizResultObj serviceResult = null;
        try {
            serviceResult = serviceProcessor.process(bizRequest, request);
        } catch (Exception e) {
            logger.error("调用业务处理异常，serviceProcessor=" + serviceProcessor.getClass()
                         + ",bizRequest=" + bizRequest);
            this.responseErrorInfo(response, result, ResultStatusEnum.BIZ_SERVICE_EXCEPTION);
            return;
        }
        serviceResult.setSessionId(result.getResult().getSessionId());
        result.setResult(serviceResult);

        this.responsData(response, result);
        if (logger.isInfoEnabled()) {
            logger.info("服务处理结果：result：" + result);
        }
    }

    /**
     * <pre>
     * 安全性校验。并把校验结果写到result中
     * </pre>
     * @param request
     * @param response
     * @param result
     * @param bizRequest
     * @return 是否校验成功
     */
    private boolean validateSafe(HttpServletRequest request, HttpServletResponse response,
                                 AppServerResult result, BaseRequest bizRequest) {
        if (bizRequest.isAuthCodeValidate() && StringUtil.isNotBlank(bizRequest.getAuthCode())) {
            //1.如果有授权码，则通过授权码获取令牌
            return authCodeValidate(request, result, bizRequest);
        } else if (!bizRequest.isAuthCodeValidate()
                   && StringUtil.isNotBlank(bizRequest.getSessionId())) {
            //2.如果没有授权码，有sessionId，则校验sessionId有效性
            return sessionIdValidate(result, bizRequest);
        } else {
            result.setResultStatus(ResultStatusEnum.REQUEST_DATA_ERROR);
            result.setMemo(ResultStatusEnum.REQUEST_DATA_ERROR.getMessage());
            return false;
        }
    }

    /**
     * <pre>
     * sessionId校验
     * </pre>
     * @param result
     * @param bizRequest
     * @return
     */
    private boolean sessionIdValidate(AppServerResult result, BaseRequest bizRequest) {
        /*boolean validSuccess = clientAccessTokenService.validateCliAccToken(
            bizRequest.getSessionId(), bizRequest.getAliUserId());

        if (validSuccess) {
            result.setResultStatus(ResultStatusEnum.ACCESS_SUCCESS);
            return true;
        } else {
            result.setResultStatus(ResultStatusEnum.ACCESS_DENY);
            result.setMemo(ResultStatusEnum.ACCESS_DENY.getMessage());
            return false;
        }*/
        return true;
    }

    /**
     * <pre>
     * 授权码校验
     * </pre>
     * @param request
     * @param result
     * @param bizRequest
     * @return
     */
    private boolean authCodeValidate(HttpServletRequest request, AppServerResult result,
                                     BaseRequest bizRequest) {
        /*TokenResult tokenResult = authService.authCodeValidate(bizRequest.getAuthCode(),
            bizRequest.getAppId());
        if (tokenResult.isSuccess()) {
            //授权完成后生成新的分布式sessionId，用于后续的和客户端交互中sessionId安全性校验; session不过期，当下次新授权码校验的时候重新生成。（不过期的原因是，这个sessionID实际上只是一个token，用来保证安全）
            String cliAccToken = clientAccessTokenService.genNewCliAccToken(request,
                tokenResult.getAlipayUserId());
            if (cliAccToken == null) {
                result.setResultStatus(ResultStatusEnum.SYSTEM_ERROR);
                result.setMemo(ResultStatusEnum.SYSTEM_ERROR.getMessage());
                return false;
            }
            result.setResultStatus(ResultStatusEnum.ACCESS_SUCCESS);
            result.getResult().setSessionId(cliAccToken);
            return true;
        } else {
            result.setResultStatus(ResultStatusEnum.ACCESS_DENY);
            result.setMemo(ResultStatusEnum.ACCESS_DENY.getMessage());
            return false;
        }*/
        return true;
    }

    /**
     * <pre>
     * 返回错误结果
     * </pre>
     * @param response
     * @param result
     * @param errorCode
     */
    private void responseErrorInfo(HttpServletResponse response, AppServerResult result,
                                   ResultStatusEnum errorCode) {
        result.setMemo(errorCode.getMessage());
        result.setResultStatus(errorCode);
        this.responsData(response, result);
    }

    /**
     * <pre>
     * 用json形式返回结果 数据
     * </pre>
     * @param obj
     */
    private void responsData(HttpServletResponse httpServletResponse, Object obj) {
        String jsonString = JsonUtil.object2Json(obj);
        try {
            httpServletResponse.setCharacterEncoding("utf-8");
            httpServletResponse.setHeader("Content-type", "text/html;charset=utf-8");
            PrintWriter writer = httpServletResponse.getWriter();
            writer.print(jsonString);
            // 无需flush和close，Tomcat会帮我处理
        } catch (IOException e) {
            logger.error("返回结果数据IO异常", e);
        }

    }

    public void setServiceProcessorFactory(ServiceProcessorFactory serviceProcessorFactory) {
        this.serviceProcessorFactory = serviceProcessorFactory;
    }

}
